
-- completed
----------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

package our_types is
  type display_type is record
    min1 : unsigned(3 downto 0);
    min0 : unsigned(3 downto 0);
    sec1 : unsigned(3 downto 0);
    sec0 : unsigned(3 downto 0);
    hun1 : unsigned(3 downto 0);
    hun0 : unsigned(3 downto 0);
  end record display_type;
end package our_types;

--------------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.our_types.all;

entity stopwatch is
  port( start_stop, lap_reset, clk100kHz : in std_logic;
        sw_display : out display_type := ("0000", "0000", "0000", "0000", "0000", "0000") );

--  check : assert not(start_stop and lap_reset) report "Incorrect use, both start/stop and lap/reset cannot be ON at same time"; 
  
end entity stopwatch;

architecture behavioral of stopwatch is
begin
  sw_beh : process(clk100kHz) is
    variable current_time_in_deci_seconds : integer := 0;
    variable current_time_in_seconds : integer :=0;
    variable current_time_in_minutes : integer :=0;
    variable deci_sec: integer:=0;
    variable sec: integer:=0;
    variable min: integer:=0;
    variable deci_tick: integer :=0;
    variable start_stop_press_count:integer :=0;
    variable ss_pressed: bit:='0';
    variable lap_reset_press_count: integer :=0;
    variable lr_pressed: bit:='0';
    variable sw_lap_reset:bit:='0';
    variable transfer_to_display: bit:='0';  
  begin
    if rising_edge(clk100kHz) then

      if start_stop='1'and ss_pressed='0'then
        ss_pressed :='1';
      end if;
      
      if ss_pressed='1' and start_stop='0'then
        start_stop_press_count := start_stop_press_count + 1;
        ss_pressed:='0';
        transfer_to_display:='1';
      end if;
      
      if lap_reset='1'and lr_pressed='0'then
        lr_pressed :='1';
      end if;
      
      if lr_pressed='1' and lap_reset='0'then
        lap_reset_press_count := lap_reset_press_count + 1;
        lr_pressed:='0';
        sw_lap_reset:='1';
        transfer_to_display:='0';
        
        if (lap_reset_press_count mod 2) =0 then
        transfer_to_display:='1';
        else
        transfer_to_display:='0';
        end if;
             
      end if;
      
         
      
      if (start_stop_press_count mod 2)=1 then
         sw_lap_reset:='0'; --added to nullify unwanted reset happened when lap followed by stop
        deci_tick := deci_tick + 1;
        if (deci_tick mod 1000)= 0 then
          current_time_in_deci_seconds:= current_time_in_deci_seconds + 1;
        end if;
      else

        transfer_to_display:='0';
        if sw_lap_reset='1'then
          lap_reset_press_count:=0;
          deci_tick :=0;
          current_time_in_deci_seconds:=0;
          sw_display <= ("0000","0000","0000","0000","0000","0000");
          transfer_to_display:='1';
         
        end if;
        
      end if;
      
      
      
      
      
      if transfer_to_display='1'then
            
            current_time_in_seconds:=current_time_in_deci_seconds/100;
            current_time_in_minutes:=current_time_in_seconds/60;
          
            deci_sec := current_time_in_deci_seconds mod 100;
            sw_display.hun1 <= to_unsigned(deci_sec mod 10,4);
            sw_display.hun0 <= to_unsigned(deci_sec / 10,4);
            
            sec := current_time_in_seconds mod 60;
            sw_display.sec1 <= to_unsigned(sec mod 10,4);
            sw_display.sec0 <= to_unsigned(sec / 10,4);
                        
            min := current_time_in_minutes mod 60;
            sw_display.min1 <= to_unsigned(min mod 10,4);
            sw_display.min0 <= to_unsigned(min / 10,4);

      end if;        
        
    end if;
    
  end process sw_beh;
end architecture behavioral;

--------------------------------------------------------------------------------




library ieee;
use ieee.std_logic_1164.all;
use work.our_types.all;

entity testbench is
end entity testbench;

architecture behavioral of testbench is
  signal clk, reset, ss, lr : std_logic;

  signal out_beh, out_rtl : display_type := ("0000", "0000", "0000", "0000", "0000", "0000");
begin
test_behavioral:  entity work.stopwatch(behavioral) port map (ss, lr, clk,out_beh);

  --entity work.stopwatch(structural)
    --  port map (ss, lr, clk, reset, out_rtl);

    process is
  begin
    clk <= '1';
    wait for 0.05 us;
    clk <= '0';
    wait for 0.05 us;
  end process;
  
  process is
  begin
    
   -- start initially  
    ss <= '0', '1' after 0.1 us, '0' after 0.2 us ;  -- Assign signals
    wait for 10001 us ;
    if out_beh /=("0000", "0000", "0001", "0000", "0000", "0000") then -- check for one second
    ASSERT false
    REPORT "behavioral not correct(check for one second)"
    SEVERITY failure;
  end if;
     ss <= '0', '1' after 0.1 us, '0' after 0.2 us ;  -- Assign signals-- -- check for stop and test 1 st value
    wait for 10 us ; 
     if out_beh /=("0000", "0000", "0001", "0000", "0000", "0000") then
    ASSERT false
    REPORT "behavioral not correct(check for stop and test value)"
    SEVERITY failure;
    end if;
    
     ss <= '0', '1' after 0.1 us, '0' after 0.2 us ;  -- Assign signals
    wait for 10001 us ;
    if out_beh /=("0000", "0000", "0010", "0000", "0000", "0000") then -- check for stop-start-stop
    ASSERT false
    REPORT "behavioral not correct check for stop-start-stop"
    SEVERITY failure;
  end if;
  
   ss <= '0', '1' after 0.1 us, '0' after 0.2 us ;  -- Assign signals-- -- check for stop and 2nd value
    wait for 10 us ; 
     if out_beh /=("0000", "0000", "0010", "0000", "0000", "0000") then
    ASSERT false
    REPORT "behavioral not correct  check for stop and 2nd value"
    SEVERITY failure;
    end if;
    
     lr <= '0', '1' after 0.1 us, '0' after 0.2 us ;  -- Assign signals  ---- check for reset ie  lap/reset is pressed when counter is stopped 
    wait for 10 us ; 
     if out_beh /=("0000", "0000", "0000", "0000", "0000", "0000") then
    ASSERT false
    REPORT "behavioral reset is not correct"
    SEVERITY failure;
    end if;
    
    ss <= '0', '1' after 0.1 us, '0' after 0.2 us ;  -- Assign signals
    wait for 10001 us ;
    if out_beh /=("0000", "0000", "0001", "0000", "0000", "0000") then -- check for start again and check value
    ASSERT false                                                       -- changes made when this happens lap_reset_press_count is 1 which makes transfer_to_display 0 
    REPORT "behavioral not correct check for start after reset"
    SEVERITY failure;
    end if;
    
    lr <= '0', '1' after 0.1 us, '0' after 0.2 us ;  -- Assign signals  ---- check for lap 
     wait for 1 us ; 
     if out_beh /=("0000", "0000", "0001", "0000", "0000", "0000") then
    ASSERT false
    REPORT "behavioral is not correct latched while running"
    SEVERITY failure;
    end if;
    wait for 10001 us ;
    
    lr <= '0', '1' after 0.1 us, '0' after 0.2 us ;  -- Assign signals  ---- check for lap 
    wait for 1 us ; 
     if out_beh /=("0000", "0000", "0010", "0000", "0000", "0000") then
    ASSERT false
    REPORT "behavioral is not correct latched previous state is also latched (checked with updated value)"
    SEVERITY failure;
    end if;
    
     ss <= '0', '1' after 0.1 us, '0' after 0.2 us ;  -- Assign signals
    wait for 10 us ;
    if out_beh /=("0000", "0000", "0010", "0000", "0000", "0000") then -- check for start again and check value
    ASSERT false
    REPORT "behavioral not correct previous input is lap and stop is pressed currently   "
    SEVERITY failure;
    end if;
    
     ss <= '0', '1' after 0.1 us, '0' after 0.2 us ;  -- Assign signals
    wait for 10001 us ;
    if out_beh /=("0000", "0000", "0011", "0000", "0000", "0000") then -- check for start again and check value
    ASSERT false
    REPORT "behavioral not correct previous input is stop and start is pressed currently and runs for 10001 us  "
    SEVERITY failure;
    end if;
    
    
    lr <= '0', '1' after 0.1 us, '0' after 0.2 us ;  -- Assign signals  ---- check for lap 
             wait for 10 us ;

     if out_beh /=("0000", "0000", "0011", "0000", "0000", "0000") then
    ASSERT false
    REPORT "behavioral is not correct latched while running"
    SEVERITY failure;
    end if;
    wait for 10011 us ;
    
    lr <= '0', '1' after 0.1 us, '0' after 0.2 us ;  -- Assign signals  ---- check for lap 
        wait for 10 us ;

     if out_beh /=("0000", "0000", "0100", "0000", "0000", "0000") then
    ASSERT false
    REPORT "behavioral is not correct latched previous state is also latched (checked with updated value)"
    SEVERITY failure;
    end if;
    wait for 10011 us ; 
    
    lr <= '0', '1' after 0.1 us, '0' after 0.2 us ;  -- Assign signals  ---- check for lap 
         wait for 10 us ;

     if out_beh /=("0000", "0000", "0101", "0000", "0000", "0000") then
    ASSERT false
    REPORT "behavioral is not correct latched while running"
    SEVERITY failure;
    end if;
    wait for 10051 us ;
    
    
   
    
    
    ss <= '0', '1' after 0.1 us, '0' after 0.2 us ;  -- Assign signals
    wait for 10 us ;
    if out_beh /=("0000", "0000", "0101", "0000", "0000", "0000") then -- check for start again and check value
    ASSERT false
    REPORT "behavioral not correct just stopping   "
    SEVERITY failure;
    end if;
    
    lr <= '0', '1' after 0.1 us, '0' after 0.2 us ;  -- Assign signals  ---- check for reset ie  lap/reset is pressed when counter is stopped 
    wait for 10 us ; 
     if out_beh /=("0000", "0000", "0000", "0000", "0000", "0000") then
    ASSERT false
    REPORT "behavioral reset is not correct"
    SEVERITY failure;
    end if;
  
  
  
    
 

  end process;

  -- Ovserver process:
  --process (clk) is
  --begin
  --  if rising_edge(clk) then
  --    if reset = '0' and out_beh /= out_rtl then
  --      ASSERT false
  --      REPORT "RTL and behavioral impl. not equal"
  --     SEVERITY failure;
  --    end if;
  --  end if;
  --end process;

  -- Clock generator:


end architecture behavioral;
   